package xcmg.device.service.ratingManager;

import com.github.pagehelper.PageInfo;
import yb.ecp.fast.infra.util.PageHelperPlus;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.company.CompanyDealerDO;
import xcmg.device.dao.entity.company.DealerClassDO;
import xcmg.device.dao.entity.ratingManager.AccountOverdueConfigDO;
import xcmg.device.dao.mapper.CompanyDealerMapper;
import xcmg.device.dao.mapper.DealerClassMapper;
import xcmg.device.dao.mapper.ratingManager.AccountOverdueConfigDOMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExcelUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.ratingManager.AccountOverdueConfigVO;
import xcmg.device.service.vo.ratingManager.BasisQueryVO;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by wrg on 2019/7/10.
 */
@Service
public class AccountOverdueConfigService {
    @Autowired
    private FastGenClient genClient;
    @Autowired
    private AccountOverdueConfigDOMapper accountOverdueConfigDOMapper;
    @Value("${spring.file.download.path}")
    private String filePath;
    private String templateExcelFileName = "AccountOverdueConfig.xls";
    @Autowired
    private HttpServletResponse response;
    @Autowired
    private CompanyDealerMapper companyDealerMapper;
    @Autowired
    private DealerClassMapper dealerClassMapper;

    private final static String AGENT_TYPE = "常规代理商";

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode remove(List<String> ids) throws Exception {
        for (String id : ids) {
            int deleteCount = accountOverdueConfigDOMapper.deleteByPrimaryKey(id);
            if (deleteCount <= 0) {
                throw new Exception("删除失败");
            }
        }

        return ErrorCode.Success;
    }


    @Transactional(rollbackFor = Exception.class)
    public ErrorCode update(AccountOverdueConfigVO accountOverdueConfigVO) throws Exception {
        AccountOverdueConfigDO record = new AccountOverdueConfigDO();
        BeanUtils.copyProperties(accountOverdueConfigVO, record);
        CompanyDealerDO companyDealerDO = companyDealerMapper.item(Long.valueOf(record.getClientId()));
        if (null == companyDealerDO){
            return ErrorCode.DealerInfoNotExist;
        }
        //客户信用额度
        BigDecimal customerQuota = companyDealerDO.getTotalLimit().subtract(
                companyDealerDO.getUsedLimit() == null ? BigDecimal.ZERO : companyDealerDO.getUsedLimit());
        record.setOneAccountControl(getAccountControl(record.getOneRealAccount(), customerQuota));
        record.setTwoAccountControl(getAccountControl(record.getTwoRealAccount(), customerQuota));
        record.setThreeAccountControl(getAccountControl(record.getThreeRealAccount(), customerQuota));
        BigDecimal decimalScore = getScore(record, customerQuota);

        record.setScore(decimalScore);
        record.setModifyTime(new Date());
        return accountOverdueConfigDOMapper.updateByPrimaryKeySelective(record) > 0 ? ErrorCode.Success : ErrorCode.Failure;
    }

     BigDecimal getScore(AccountOverdueConfigDO record, BigDecimal customerQuota) {
         /**实际回款大于等于计划回款值或者实账小于等于信用额度 不扣分 其他都扣分*/
        BigDecimal decimalScore = BigDecimal.ZERO;
        BigDecimal oneActualPayment1 = record.getOneActualPayment();
        BigDecimal oneReturnTarget1 = record.getOneReturnTarget();
        BigDecimal oneRealAccount1 = record.getOneRealAccount();
         if (oneActualPayment1.compareTo(oneReturnTarget1) < 0 && oneRealAccount1.compareTo(customerQuota) > 0) {
             decimalScore = decimalScore.subtract(new BigDecimal(10));
         }

         BigDecimal twoActualPayment1 = record.getTwoActualPayment();
        BigDecimal twoReturnTarget1 = record.getTwoReturnTarget();
        BigDecimal twoRealAccount1 = record.getTwoRealAccount();
         if (twoActualPayment1.compareTo(twoReturnTarget1) < 0 && twoRealAccount1.compareTo(customerQuota) > 0) {
             decimalScore = decimalScore.subtract(new BigDecimal(10));
         }

         BigDecimal threeActualPayment1 = record.getThreeActualPayment();
        BigDecimal threeReturnTarget1 = record.getThreeReturnTarget();
        BigDecimal threeRealAccount1 = record.getThreeRealAccount();
         if (threeActualPayment1.compareTo(threeReturnTarget1) < 0 && threeRealAccount1.compareTo(customerQuota) > 0) {
             decimalScore = decimalScore.subtract(new BigDecimal(10));
         }
         return decimalScore;
    }

    public PageCommonVO list(SearchCommonVO<BasisQueryVO> condition) {
        PageHelperPlus.orderBy("create_time,id desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<AccountOverdueConfigDO> doList = accountOverdueConfigDOMapper.selectByRatingId(condition.getFilters());
        List<AccountOverdueConfigVO> voList = new ArrayList<>();
        for (AccountOverdueConfigDO accountOverdueConfigDO : doList) {
            AccountOverdueConfigVO accountOverdueConfigVO = new AccountOverdueConfigVO();
            BeanUtils.copyProperties(accountOverdueConfigDO, accountOverdueConfigVO);
            voList.add(accountOverdueConfigVO);
        }
        PageCommonVO<AccountOverdueConfigVO> result = new PageCommonVO<>();
        result.setPageInfo(new PageInfo<>(doList));
        result.setPageInfoList(voList);
        return result;
    }

    public AccountOverdueConfigVO item(String id) {
        AccountOverdueConfigDO accountOverdueConfigDO = accountOverdueConfigDOMapper.selectByPrimaryKey(id);
        AccountOverdueConfigVO accountOverdueConfigVO = new AccountOverdueConfigVO();
        if (null != accountOverdueConfigDO) {
            BeanUtils.copyProperties(accountOverdueConfigDO, accountOverdueConfigVO);
        }
        return accountOverdueConfigVO;
    }

    public void download() throws Exception {
        FileUtil.downLoadFile(response, filePath, templateExcelFileName);
    }


    public FunctionResult importExcel(InputStream in, String ratingId, String userId, String userName, String orgId) throws Exception {
        FunctionResult result = new FunctionResult();
        HSSFWorkbook wb = new HSSFWorkbook(in);
        HSSFSheet sheet = wb.getSheetAt(0);
        int totalRow = sheet.getLastRowNum();
        if (totalRow < 2) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        int totalCell = sheet.getRow(2).getLastCellNum();
        if (totalCell != 12) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }

        List<AccountOverdueConfigVO> errorDetailVOList = new ArrayList<>();
        boolean success;
        for (int i = 2; i <= totalRow; i++) {
            HSSFRow curRow = sheet.getRow(i);
            AccountOverdueConfigVO accountOverdueConfigVO = new AccountOverdueConfigVO();
            if (curRow == null) {
                continue;
            }
            if (isRowEmpty(curRow)) {
                continue;
            }

            String oneReturnTarget = excelValue(curRow, 3);
            String oneActualPayment = excelValue(curRow, 4);
            String oneRealAccount = excelValue(curRow, 5);
            String twoReturnTarget = excelValue(curRow, 6);
            String twoActualPayment = excelValue(curRow, 7);
            String twoRealAccount = excelValue(curRow, 8);
            String threeReturnTarget = excelValue(curRow, 9);
            String threeActualPayment = excelValue(curRow, 10);
            String threeRealAccount = excelValue(curRow, 11);
            boolean checkResult = checkFormat(errorDetailVOList, i, accountOverdueConfigVO, oneReturnTarget, oneActualPayment, oneRealAccount,
                    twoReturnTarget,twoActualPayment,twoRealAccount,threeReturnTarget,threeActualPayment,threeRealAccount);
            if (checkResult) {
                continue;
            }

            String clientNo = excelValue(curRow, 1);
            CompanyDealerDO companyDealerDO = companyDealerMapper.itemByDealerCode(orgId, clientNo);
            if (companyDealerDO == null) {
                accountOverdueConfigVO.setErrorRow(i + 1);
                accountOverdueConfigVO.setRemark("客户信息不存在");
                errorDetailVOList.add(accountOverdueConfigVO);
                continue;
            }
            Long dealerClassId = companyDealerDO.getDealerClassId();
            if (null == dealerClassId) {
                accountOverdueConfigVO.setErrorRow(i + 1);
                accountOverdueConfigVO.setRemark("客户不是常规代理商");
                errorDetailVOList.add(accountOverdueConfigVO);
                continue;
            }
            DealerClassDO dealerClassDO = dealerClassMapper.item(dealerClassId);
            if (null == dealerClassDO || !dealerClassDO.getClassName().equals(AGENT_TYPE)) {
                accountOverdueConfigVO.setErrorRow(i + 1);
                accountOverdueConfigVO.setRemark("客户不是常规代理商");
                errorDetailVOList.add(accountOverdueConfigVO);
                continue;
            }

            int count = accountOverdueConfigDOMapper.countByRatingIdClientId(ratingId, String.valueOf(companyDealerDO.getId()));
            if (count > 0) {
                accountOverdueConfigVO.setErrorRow(i + 1);
                accountOverdueConfigVO.setRemark("客户信息已存在");
                errorDetailVOList.add(accountOverdueConfigVO);
                continue;
            }
            AccountOverdueConfigDO record = new AccountOverdueConfigDO();
            record.setRatingId(ratingId);
            record.setClientId(String.valueOf(companyDealerDO.getId()));
            record.setClientName(companyDealerDO.getCompanyName());
            record.setCreateTime(new Date());
            record.setCreatorId(userId);
            record.setCreatorName(userName);

            //客户信用额度
            BigDecimal customerQuota = companyDealerDO.getTotalLimit().subtract(
                    companyDealerDO.getUsedLimit() == null ? BigDecimal.ZERO : companyDealerDO.getUsedLimit());
            record.setOneActualPayment(new BigDecimal(oneActualPayment));
            record.setOneRealAccount(new BigDecimal(oneRealAccount));
            record.setOneReturnTarget(new BigDecimal(oneReturnTarget));
            record.setTwoActualPayment(new BigDecimal(twoActualPayment));
            record.setTwoRealAccount(new BigDecimal(twoActualPayment));
            record.setTwoReturnTarget(new BigDecimal(twoActualPayment));
            record.setOneAccountControl(getAccountControl(new BigDecimal(oneRealAccount), customerQuota));
            record.setTwoAccountControl(getAccountControl(new BigDecimal(twoRealAccount), customerQuota));
            record.setThreeAccountControl(getAccountControl(new BigDecimal(threeRealAccount), customerQuota));
            record.setThreeActualPayment(new BigDecimal(threeActualPayment));
            record.setThreeRealAccount(new BigDecimal(threeActualPayment));
            record.setThreeReturnTarget(new BigDecimal(threeActualPayment));

            BigDecimal decimalScore = getScore(record, customerQuota);
            record.setScore(decimalScore);
            String id = genClient.newGuidText().getValue();
            if (StringUtils.isBlank(id)) {
                accountOverdueConfigVO.setErrorRow(i + 1);
                accountOverdueConfigVO.setRemark("主键生成失败");
                errorDetailVOList.add(accountOverdueConfigVO);
                continue;
            }
            record.setId(id);
            success = accountOverdueConfigDOMapper.insertSelective(record)>0;
            if (!success) {
                accountOverdueConfigVO.setErrorRow(i + 1);
                accountOverdueConfigVO.setRemark("应收账款逾期配置失败，客户编码：" + clientNo);
                errorDetailVOList.add(accountOverdueConfigVO);
            }
        }

        getImportResult(result, errorDetailVOList);
        return result;
    }

    private String getAccountControl(BigDecimal realAccount, BigDecimal customerQuota) {
        if (customerQuota == null){
            customerQuota = BigDecimal.ZERO;
        }
        if(realAccount.compareTo(BigDecimal.ZERO)<= 0) {
            return "清零";
        }else if (realAccount.compareTo(customerQuota) <= 0){
            return "额度内";
        }else{
            return "额度外";
        }
    }

    static void getImportResult(FunctionResult result, List<?> errorDetailVOList) {
        if (errorDetailVOList.isEmpty()) {
            result.setValue(new ArrayList<>());
            result.setCode(ErrorCode.Success);
        } else {
            result.setValue(errorDetailVOList);
            result.setCode(ErrorCode.IllegalArument);
        }
    }

    private boolean checkFormat(List<AccountOverdueConfigVO> errorDetailVOList, int i,
                                AccountOverdueConfigVO accountOverdueConfigVO, String oneReturnTarget, String oneActualPayment,
                                String oneRealAccount, String twoReturnTarget,String twoActualPayment,String twoRealAccount,
                                String threeReturnTarget,String threeActualPayment,String threeRealAccount) {
        if (!isInteger(oneReturnTarget)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第一次回款目标格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(oneReturnTarget).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第一次回款目标过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(oneActualPayment)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第一次实际回款格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(oneActualPayment).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第一次实际回款过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(oneRealAccount)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第一次实账格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(oneRealAccount).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第一次实账过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(twoReturnTarget)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第二次回款目标格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(twoReturnTarget).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第二次回款目标过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(twoActualPayment)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第二次实际回款格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(twoActualPayment).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第二次实际回款过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(twoRealAccount)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第二次实账格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(twoRealAccount).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第二次实账过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(threeReturnTarget)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第三次回款目标格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(threeReturnTarget).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第三次回款目标过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(threeActualPayment)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第三次实际回款格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(threeActualPayment).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第三次实际回款过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        if (!isInteger(threeRealAccount)) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第三次实账格式不正确");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }
        if (new BigDecimal(threeRealAccount).compareTo(BigDecimal.valueOf(9999999999.99)) > 0) {
            accountOverdueConfigVO.setErrorRow(i + 1);
            accountOverdueConfigVO.setRemark("第三次实账过大");
            errorDetailVOList.add(accountOverdueConfigVO);
            return true;
        }

        return false;
    }

    private String excelValue(HSSFRow curRow, Integer line) {
        Cell cell = curRow.getCell(line);
        String cellValue = "";
        if (null != cell) {
            // 以下是判断数据的类型
            switch (cell.getCellType()) {
                case HSSFCell.CELL_TYPE_NUMERIC: // 数字
                    DecimalFormat df = new DecimalFormat("0");
                    cellValue = df.format(cell.getNumericCellValue());
                    break;

                case HSSFCell.CELL_TYPE_STRING: // 字符串
                    cellValue = cell.getStringCellValue();
                    break;

                case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                    cellValue = cell.getBooleanCellValue() + "";
                    break;

                case HSSFCell.CELL_TYPE_FORMULA: // 公式
                    cellValue = cell.getCellFormula() + "";
                    break;

                case HSSFCell.CELL_TYPE_BLANK: // 空值
                    cellValue = "";
                    break;

                case HSSFCell.CELL_TYPE_ERROR: // 故障
                    cellValue = "";
                    break;

                default:
                    cellValue = "";
                    break;
            }
        }
        return cellValue;
    }

    public static boolean isRowEmpty(HSSFRow row) {
        for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
            HSSFCell cell = row.getCell(c);
            if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK && !StringUtil.isNullOrSpace(ExcelUtil.getCellStringValue(cell))) {
                return false;
            }
        }
        return true;
    }

    private boolean isInteger(String str) {
        if (null == str || "".equals(str)) {
            return false;
        }
        try {
            BigDecimal decimal = new BigDecimal(str);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

}
